#!/usr/bin/python

import re
import hashlib
import logging
from google.appengine.api import urlfetch
from hashlib import md5

def fetch(url, username, password, domain):
    method = 'GET'
    res = urlfetch.fetch(url)
    if res.status_code != 401:
        return res
    if 'WWW-Authenticate' not in res.headers:
        raise Exception("No WWW-Authenticate header is found")
    www_auth = res.headers['WWW-Authenticate']
    params = dict()
    if re.match('^\s*Digest', www_auth):
        www_auth = re.sub('^\s*Digest', '', www_auth)
    else:
        raise Exception("Not a digest authentication!")
    for pair in www_auth.split(','):
        key, val = pair.split('=')
        params[key.lstrip()] = val.lstrip('"').rstrip('"')

    try:
        dom = params['realm']
        if dom != domain:
            raise Exception("The domain is different from the one given to us!")
    except:
        raise Exception("No realm in the WWW-Authenticate header!")

    try:
        if params['qop'] != 'auth':
            raise Exception("No qop other than auth is supported")
    except:
        raise Exception("No qop is present in the WWW-Authenticate")

    if 'algorithm' in params and params['algorithm'] != 'MD5':
        raise Exception("The only algorithm supported is MD5")

    ha1 = md5("%s:%s:%s" % (username, domain, password)).hexdigest()
    ha2 = md5("%s:%s" % (method, url)).hexdigest()
    response = md5("%s:%s:%s:%s:%s:%s" % (ha1, params['nonce'], "00000001", "0a4f113b", params['qop'], ha2)).hexdigest()
    auth_header = "Digest username=\"%s\", realm=\"%s\", nonce=\"%s\", uri=\"%s\", qop=auth, nc=00000001, cnonce=\"0a4f113b\", response=\"%s\"" % (username, domain, params['nonce'], url, response)
    return urlfetch.fetch(url=url, headers={'Authorization': auth_header})
